package org.ns.framework.datasource.mybatis;

import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.TransactionIsolationLevel;
/**
 * Mybatis 的事务管理最终实现.
 * 
 * @author zhangxingyu
 *
 */
public class MybatisTransactionManage extends MybatisTransactionReference {

	private ExecutorType executorType; // 事务执行类型 SIMPLE, REUSE, BATCH

	private TransactionIsolationLevel level; // 事物级别
	/**
	 * SqlSession-记录
	 */
	private Map<String, SqlSession> sqlSessionMap = new HashMap<>();
	
	private boolean close = false;
	
	// 不允许通过其他方式创建.
	MybatisTransactionManage() {}
	
	/**
	 * 设置执行类型
	 * 
	 * @param executorType
	 */
	protected void setExecutorType(ExecutorType executorType) {
		this.executorType = executorType;
	}
	
	/**
	 * 执行方式.
	 * @return
	 */
	protected ExecutorType getExecutorType() {
		return executorType;
	}

	/**
	 * 设置事物级别
	 * 
	 * @param level
	 */
	protected void setLevel(TransactionIsolationLevel level) {
		this.level = level;
	}
	/**
	 * 事务隔离级别
	 * @return
	 */
	protected TransactionIsolationLevel getLevel() {
		return level;
	}
	
	/**
	 * 开启SqlSession
	 * 
	 * @param dataSourceName
	 * @param sqlSessionFactory
	 * @return
	 */
	@Override
	public SqlSession openSession(String dataSourceName, SqlSessionFactory sqlSessionFactory) {
		
		SqlSession sqlSession = sqlSessionMap.get(dataSourceName);
		if (sqlSession != null) {
			return sqlSession;
		}
		if (executorType == null) {
			sqlSession = sqlSessionFactory.openSession(ExecutorType.SIMPLE, level);
		} else {
			sqlSession = sqlSessionFactory.openSession(executorType, level);
		}
		sqlSessionMap.put(dataSourceName, sqlSession);
		return sqlSession;
	}

	/**
	 * 提交
	 */
	@Override
	public CommitResult commit() {
		CommitResult commitResult = new CommitResult();
		
		int reference = getReference(); // 获得提交引用变量.
		commitResult.setReference(reference);
		
		// 引用变量必须等于1才可以进行提交.
		if (reference == 1) {
			if (sqlSessionMap.size() > 0) {
				for (Map.Entry<String, SqlSession> entry : sqlSessionMap.entrySet()) {
					SqlSession sqlSession = entry.getValue();
					try {
						sqlSession.commit(true);
					} catch (Exception e) {
						e.printStackTrace();
						commitResult.addFailDataSource(entry.getKey());
					}
	
				}
			}
		}
		return commitResult;
	}
	/**
	 * 回滚
	 */
	public void rollback() {
		if (sqlSessionMap.size() > 0) {
			for (Map.Entry<String, SqlSession> entry : sqlSessionMap.entrySet()) {
				SqlSession sqlSession = entry.getValue();
				try {
					sqlSession.rollback(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 事务关闭
	 */
	@Override
	public void close() {
		
		if (close || release() > 0) { // 引用释放. 释放值等于0时
			return;
		}
		this.close = true;
		try {
			CommitResult commitResult = null;
//			if (isAutoCommit()) {
//				commitResult = commit();
//			} else {
//				rollback();
//			}
			rollback();
			if (sqlSessionMap.size() > 0) {
				for (Map.Entry<String, SqlSession> entry : sqlSessionMap.entrySet()) {
					SqlSession sqlSession = entry.getValue();
					try {
						sqlSession.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				sqlSessionMap.clear();
			}
			if (commitResult != null) {
				commitResult.throwCommitException();
			}
		} finally {
			MybatisTransactionChain.remove(); // 关闭时移除
		}
	}
}
